import * as THREE from 'three';
import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader';
// 导入控制器，轨道控制器
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
// 导入模型解析器
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";

export class Base3d {
    constructor(selector, onFinish) {
        this.container = document.querySelector(selector);
        this.scene; // 场景
        this.camera; // 摄像机
        this.renderer; // 渲染器
        this.controls; // 轨道控制器
        this.model; // 场景中的模型
        this.panzi; // 盘子
        this.animateAction;
        this.onFinish = onFinish;
        this.mixer;// 播放器
        this.clock = new THREE.Clock();
        this.init();
        this.animate();
    }

    onProgress(fn) {
        this.progressFn = fn;
    }

    init() {
        this.initScene();
        this.initCamera();
        this.initRender();
        // 添加控制器，通过鼠标可以旋转
        //this.initControls();
        // 添加物体
        this.addMesh();
        // 监听场景大小改变，调整渲染尺寸
        window.addEventListener('resize', this.onWindowResize.bind(this), false);
        // 监听滚轮事件
        window.addEventListener("mousewheel", this.onMouseWheel.bind(this));
    }

    initScene() {
        this.scene = new THREE.Scene();
        this.setEnvMap('000');
    }

    initCamera() {
        this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 200);
        this.camera.position.set(-1.8, 0.6, 2.7);
    }

    initRender() {
        this.renderer = new THREE.WebGLRenderer({
            antialias: true,// 搞锯齿
        });
        // 设置像素
        this.renderer.setPixelRatio(window.devicePixelRatio);
        // 设置屏幕大小
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        // 设置色调映射
        this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
        // 设置曝光程序
        this.renderer.toneMappingExposure = 2;// 默认为1
        this.container.appendChild(this.renderer.domElement);
    }

    // 轨道控制器
    initControls() {
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    }

    // 加载模型
    setModel(modelName) {
        return new Promise((resolve, reject) => {
            const loader = new GLTFLoader().setPath('files/gltf/');
            loader.load(modelName, (gltf) => {
                    // 添加之前删除之前模型
                    this.model && this.model.removeFromParent();
                    this.model = gltf.scene.children[0];
                    if ("bag2.glb" == modelName) { // && !this.panzi
                        this.panzi = gltf.scene.children[2];
                        //this.scene.add(this.panzi);
                        // 修改摄像头
                        this.camera = gltf.cameras[0];
                        // 调用动画
                        this.mixer = new THREE.AnimationMixer(gltf.scene.children[1]);
                        this.animateAction = this.mixer.clipAction(gltf.animations[0]);// 从模型中取出动画
                        //   设置动画播放时长、次数
                        this.animateAction.setDuration(20).setLoop(THREE.LoopOnce);
                        //   设置播放完成之后停止
                        this.animateAction.clampWhenFinished = true;
                        //   播放动画
                        // this.animateAction.play();// 取消自动播放，通过滚轮播放

                        //   设置灯光
                        this.spotlight1 = gltf.scene.children[3].children[0];
                        this.spotlight1.intensity = 1;// 调整灯光亮度
                        this.spotlight2 = gltf.scene.children[4].children[0];
                        this.spotlight2.intensity = 1;// 调整灯光亮度
                        this.spotlight3 = gltf.scene.children[5].children[0];
                        this.spotlight3.intensity = 1;// 调整灯光亮度
                    }
                    //this.scene.add(this.model);
                    this.scene.add(gltf.scene);
                    resolve(modelName + '模型加载成功！');
                },
                (e) => {
                    console.log("模型加载进度");
                    console.log(e);
                    this.progressFn(e);
                });
        });
    }

    // 添加物体
    addMesh() {
        let res = this.setModel('bag2.glb');
        if (this.onFinish) {
            this.onFinish(res);
        }
    }

    // 设置环境纹理
    setEnvMap(hdr) {
        new RGBELoader().setPath('./files/hdr/').load(hdr + '.hdr', (texture) => {
            // 指明是球形映射
            texture.mapping = THREE.EquirectangularReflectionMapping;
            this.scene.background = texture;
            this.scene.environment = texture;
        });
    }

    render() {
        // 获取帧与帧之间的时间差
        let delta = this.clock.getDelta();
        this.mixer && this.mixer.update(delta);
        this.renderer.render(this.scene, this.camera);
    }

    animate() {
        this.renderer.setAnimationLoop(this.render.bind(this));
    }

    // 窗口大小变化时，调整渲染窗口大小
    onWindowResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
    }

    onMouseWheel(e) {
        let timeScale = e.deltaY > 0 ? 1 : -1;
        this.animateAction.setEffectiveTimeScale(timeScale);
        this.animateAction.paused = false;
        this.animateAction.play();
        if (this.timeoutid) {
            clearTimeout(this.timeoutid);
        }
        this.timeoutid = setTimeout(() => {
            this.animateAction.halt(0.5);
        }, 300);
    }
}
